﻿using System;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using AutoMapper;
using MvcApplication2.Controllers.Viewmodel;
using MvcApplication2.Models;

namespace MvcApplication2.Controllers
{

    [Authorize]
    public class UserController : ControllerEx
    {
        private MvcApplication2Context db = new MvcApplication2Context();

        /// <summary>
        /// Mostra pannello di controllo
        /// </summary>
        /// <returns></returns>
        public ActionResult Dashboard()
        {
            var vm = new DashboardViewModel();

            var user = ModelHelper.GetUser(db);

            if (user.Type == "tester")
            {
                CompleteTesterDashboard(vm);
                vm.ShowTesterPanel = true;
            }
            else if (user.Type == "dev")
                vm.ShowDevPanel = true;
            else
            {
                vm.ShowDevPanel = true;
                vm.ShowTesterPanel = true;
            }

            return View(vm);
        }

        /// <summary>
        /// Aggiunge dati riguardanti lato tester per utente
        /// </summary>
        /// <param name="vm"></param>
        private void CompleteTesterDashboard(DashboardViewModel vm)
        {
            /*
             * Devo inserire i vari esericizi in corso dell'utente
             */
            var user = ModelHelper.GetUser(db);

            var works =
                db.UserMessages.Where(m => m.UsersAllowed.Any(u => u.UserProfileId == user.UserProfileId) &&
                                           m.Type == UserMessageType.TesterExercise &&
                                           (m.ExerciseStatus != ExerciseStatusType.ProposalActive &&
                                            m.ExerciseStatus != ExerciseStatusType.Eliminated)
                                           ).ToList();

            foreach (var userMessage in works)
            {
                var umvm = ModelHelper.CopyTo<UserMessage, UserMessageViewModel>(userMessage);

                vm.Works.Add(umvm);
            }
        }

        /**
        * Manda messaggio a utente,
        * Simile a send proposal.
        */
        public ActionResult ReadMessage(int id = 0)
        {
            try
            {
                var user = ModelHelper.GetUser(db);

                var messageViewModel = UserMessageHelper.UserMessageRead(db, id, user);

                switch (messageViewModel.Type)
                {
                    case UserMessageType.GenericMessage:
                        return View("SendMessage", messageViewModel);

                    case UserMessageType.TesterExercise:
                        return View("SendProposal", messageViewModel);
                }
            }
            catch (Exception)
            {
                // todo :intercetto not allowed .. oppure cerco il modo di gestire l'eccezzioni in un controller base.
                return null;
            }

            return RedirectToAction("Messages");
        }
        /**
         * Questo è per inviare reply al messaggio letto.
         * .Usato anche come typo messaggio
         */
        [HttpPost]
        public ActionResult ReadMessage(UserMessageViewModel viewModel)
        {
            try
            {
                var user = ModelHelper.GetUser(db);
                /*todo . qui invio reply . devo vedere se sono autorizzato a questa discussione*/
                var success = UserMessageHelper.UserMessageReply(db, user, viewModel);
                if (success)
                    AddSuccessMessage("Risposta inviata !");
                else
                    AddErrorMessage("Errore invio risposta !");

                return RedirectToAction("Messages");
            }
            catch (Exception)
            {
                // todo :intercetto not allowed .. oppure cerco il modo di gestire l'eccezzioni in un controller base.
                return null;
            }
        }

        public ActionResult AcceptTestExercise(int id = 0)
        {
            var test = db.UserMessages.Find(id);

            test.ExerciseStatus = ExerciseStatusType.WaitingTest;

            db.SaveChanges();

            return RedirectToAction("Messages");
        }

        public ActionResult TrashProposal(int id = 0)
        {
            var user = ModelHelper.GetUser(db);

            var test = db.UserMessages.Find(id);

            if (test != null)
            {

                test.LastMessageFrom = "tester";

                test.ExerciseStatus = ExerciseStatusType.Rejected;

                if (test.UsersAllowed.Contains(user))
                    test.UsersAllowed.Remove(user);

                db.SaveChanges();

                /*
             * vedere come fare per cancellarlo.
             */
            }

            return RedirectToAction("Messages");
        }

        /*todo :
         * fare qui i metodi manda proposta test e to dev 
         */

        /**
         * Manda messaggio a utente,
         * Simile a send proposal.
         */
        public ActionResult SendMessage(int id = 0)
        {
            var user = ModelHelper.GetUser(db);

            var vm = UserMessageHelper.GenericMessageGet(db, id, user);

            return View(vm);
        }

        /// <summary>
        /// Qui verrà creato il messaggio di proposta
        /// </summary>
        [HttpPost]
        public ActionResult SendMessage(UserMessageViewModel mess, FormCollection formCollection)
        {
            // dove prendo destinazione qui ? faccio hidden ??
            var success = UserMessageHelper.GenericMessagePOST(db, mess.UserMessageId, mess.DestinationId, mess.Message);

            if (success)
                AddSuccessMessage("Messaggio Spedito !");

            else
            {
                AddErrorMessage("Errore spedizione messaggio ..");
            }

            return RedirectToAction("ViewProfile", new RouteValueDictionary { { "id", mess.DestinationId } });
        }
        //public ActionResult SendProposal(int id = 0)
        //{
        //    var user = ModelHelper.GetUser(db);

        //    var exmessage = UserMessageHelper.GetTesterExercise(db, id, user.UserProfileId);

        //    var vm = ModelHelper.CopyTo<UserMessage, UserMessageViewModel>(exmessage);


        //    return View(vm);
        //}

        ///// <summary>
        ///// Qui verrà creato il messaggio di proposta
        ///// </summary>
        //[HttpPost]
        //public ActionResult SendProposal(UserMessageViewModel mess, FormCollection formCollection)
        //{

        //    var success = UserMessageHelper.CreateTesterExercise(db, mess.ExerciseId, mess.TesterId, mess.Reward, mess.Message, "tester");

        //    if (success)
        //        AddSuccessMessage("Proposta Spedita !");

        //    else
        //    {
        //        AddErrorMessage("Errore spedizione proposta !");
        //    }

        //    return RedirectToAction("SearchExercises");
        //}

        public ActionResult MyProfile()
        {
            var currentUser = ModelHelper.GetUser(db);

            return RedirectToAction("ViewProfile", new RouteValueDictionary { { "id", currentUser.UserProfileId } });
        }


        [AllowAnonymous]
        public ActionResult ViewProfile(int id = 0)
        {
            var user = db.UsersProfiles.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }

            var vm = CreateViewModel(user);

            return View(vm);
        }

        //private UserProfileViewModel CreateViewModel(UserProfile user)
        //{
        //    var vm = ModelHelper.CopyTo<UserProfile, UserProfileViewModel>(user);

        //    vm.UserProfileId = user.UserProfileId;
        //    /**
        //     * fill dev property
        //     */
        //    var devReview = db.UserMessages.Include(m => m.Exercise).Where(m => m.Exercise.OwnerId == user.UserProfileId && m.Type == UserMessageType.RatingDev).ToList();

        //    vm.DevRatingCounter = devReview.Count;

        //    vm.DevRating = (double)devReview.Sum(o => o.Rating) / devReview.Count;

        //    foreach (var userMessage in devReview)
        //    {
        //        var rv = new ReviewViewModel { Message = userMessage.Message, Rating = userMessage.Rating };
        //        vm.DevReviews.Add(rv);
        //    }

        //    var testerReview = db.UserMessages.Include(m => m.Exercise).Where(m => m.TesterId == user.UserProfileId && m.Type == UserMessageType.RatingTester).ToList();

        //    vm.TesterRatingCounter = testerReview.Count;

        //    vm.TesterRating = (double)testerReview.Sum(o => o.Rating) / testerReview.Count;

        //    foreach (var userMessage in testerReview)
        //    {
        //        var rv = new ReviewViewModel { Message = userMessage.Message, Rating = userMessage.Rating };
        //        vm.TesterReviews.Add(rv);
        //    }

        //    return vm;
        //}

        private UserProfileViewModel CreateViewModel(UserProfile user)
        {
            var vm = ModelHelper.CopyTo<UserProfile, UserProfileViewModel>(user);

            vm.UserProfileId = user.UserProfileId;
            /**
             * fill dev property
             */
            var devReview = db.UserMessages.Include(m => m.Exercise).Where(m => m.RatedUser.UserProfileId == user.UserProfileId && m.Type == UserMessageType.RatingDev).ToList();

            vm.DevRatingCounter = devReview.Count;

            vm.DevRating = (double)devReview.Sum(o => o.Rating) / devReview.Count;

            foreach (var userMessage in devReview)
            {

                var rv = new ReviewViewModel { Message = userMessage.Message, Rating = userMessage.Rating, VotingUsername = userMessage.Owner.DisplayName };
                vm.DevReviews.Add(rv);
            }

            var testerReview = db.UserMessages.Include(m => m.Owner).Include(t => t.RatedUser).Where(m => m.RatedUser.UserProfileId == user.UserProfileId && m.Type == UserMessageType.RatingTester).ToList();

            vm.TesterRatingCounter = testerReview.Count;

            vm.TesterRating = (double)testerReview.Sum(o => o.Rating) / testerReview.Count;

            foreach (var userMessage in testerReview)
            {
                var rv = new ReviewViewModel { Message = userMessage.Message, Rating = userMessage.Rating, VotingUsername = userMessage.Owner.DisplayName };
                vm.TesterReviews.Add(rv);
            }

            return vm;
        }




        public ActionResult UserSetting()
        {
            var user = ModelHelper.GetUser(db);

            //var language = db.Languages.Take(2);
            //foreach (var language1 in language)
            //{
            //    user.Languages.Add(language1);
            //}

            //db.SaveChanges();

            //var vm = new UserSettingViewModel();

            // vm.CreateCheckBoxList(db);
            Mapper.CreateMap<UserProfile, UserSettingViewModel>();

            UserSettingViewModel vm = Mapper.Map<UserProfile, UserSettingViewModel>(user);

            vm.CreateCheckBoxList(db);

            return View(vm);
        }

        public string CheckUser(string username, string password)
        {
            return Membership.ValidateUser(username, password).ToString();
        }

        [HttpPost]
        public ActionResult UserSetting(UserSettingViewModel user, FormCollection formCollection)
        {
            var userm = ModelHelper.GetUser(db);

            // UpdateModel(userm,formCollection);

            user.Update(userm, db);

            db.SaveChanges();

            Mapper.CreateMap<UserProfile, UserSettingViewModel>();

            UserSettingViewModel vm = Mapper.Map<UserProfile, UserSettingViewModel>(userm);

            vm.CreateCheckBoxList(db);

            return View(vm);
        }

        public ActionResult Messages()
        {
            var user = ModelHelper.GetUser(db);

            var mess = UserMessageHelper.GetUserMessages(db, user);
            return View(mess);
        }

        /// <summary>
        /// Metodo usato per dare il voto al tester.
        /// Solo chi ha "lavorato" con tester può dare voto.
        /// todo : Quindi serve riferimento a esercizio e deve avere stato completed
        /// </summary>
        public ActionResult VoteTester(int id = 0)
        {
            var vm = UserMessageHelper.VotationUserMessageGet(db, id);

            return View("VoteUser", vm);
        }

        [HttpPost]
        public ActionResult VoteTester(UserMessageViewModel ratingMess)
        {
            var success = UserMessageHelper.VotationUserMessagePost(db, ratingMess);

            if (success)
                AddSuccessMessage("Invio rating ok !");
            else
            {
                AddErrorMessage("Invio rating error");
            }

            // cercare di reinderizzare alla pagina dalla quale si è partiti
            return RedirectToAction("ViewProfile", new RouteValueDictionary { { "id", ratingMess.DestinationId } });
        }




        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }

    }
}